﻿using System;
using System.Collections.Specialized;
using System.Text;

namespace Business.Logic
{
    public class StringUtil
    {

        protected static string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";

        /// <summary>
        /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
        /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
        /// </summary>
        /// <param name="value">The value to Url encode</param>
        /// <returns>Returns a Url encoded string</returns>
        public static string UrlEncode(string value)
        {
            StringBuilder result = new StringBuilder();

            foreach (char symbol in value)
            {
                if (unreservedChars.IndexOf(symbol) != -1)
                {
                    result.Append(symbol);
                }
                else if (symbol == ' ') result.Append("+");
                else
                {
                    result.Append('%' + String.Format("{0:X2}", (int)symbol));
                }
            }

            return result.ToString();
        }

        /// <summary>
        /// TBI
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public static string UrlDecode(string s)
        {
            string ret = "";
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == '%')
                {
                    string hex = "" + s[i + 1] + s[i + 2];
                    // Convert the number expressed in base-16 to an integer.
                    int value = Convert.ToInt32(hex, 16);
                    // Get the character corresponding to the integral value.
                    char c = (char)value;
                    ret += c;
                    i += 2;
                }
                else ret += s[i];
            }
            ret = ret.Replace("+", " ");
            ret = ret.Replace("&amp;", "&");
            return ret;
        }


        public static NameValueCollection ParseQueryString(string response)
        {
            var nc = new NameValueCollection();
            string q = response;
            if (response.Contains("?"))
            {
                int ix = response.IndexOf("?");
                if (response.Length > ix+1)  q = response.Substring(ix + 1);
                else return nc; // empty params
            }
            string[] split = q.Split('&');
            foreach (var elem in split)
            {
                string[] nameVal = elem.Split('=');
                if (nameVal.Length == 2)
                    nc.Add(nameVal[0], nameVal[1]);
            }
            return nc;
        }

        /// <summary>
        /// Converts milliseconds since 01.01.1970 to a datetime object
        /// </summary>
        /// <returns></returns>
        public static DateTime GooglTimeToDateTime(long googleTime)
        {
            double ms = Convert.ToDouble(googleTime);
            DateTime dt = new DateTime(1970, 01, 01).AddMilliseconds(ms);
            var local = dt.ToLocalTime();
            return local;
        }

        public static long DateTimeToGoogleTime(DateTime date)
        {
            var start = new DateTime(1970, 01, 01);
            var dateUtc = date.ToUniversalTime();
            return (long )dateUtc.Subtract(start).TotalMilliseconds;
        }

        /// <summary>
        /// URL Encodes and converts non-standard characters to a string representing unicode value in the format
        /// \uXXXX where XXXX = unicode value
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        internal static string GoogleEncode(string text)
        {
            var sb = new StringBuilder();
            for (int i = 0; i < text.Length; i++)
            {
                int val = (int) text[i];
                if (val > 127)
                {
                    string u = String.Format("\\u{0:x4}", val);
                    sb.Append(u);
                }
                else sb.Append(text[i]);
            }
            var urlEncoded = UrlEncode(sb.ToString());
            return urlEncoded;
        }

        /// <summary>
        /// Performs a string comparison where NULL and String.Empty is treated equally.
        /// </summary>
        /// <param name="s1">First string</param>
        /// <param name="s2">Second string</param>
        /// <returns>True if equals</returns>
        public static bool EqualsOrNull(string s1, string s2)
        {
            if (s1 == String.Empty && s2 == null) return true;
            if (s1 == null && s2 == String.Empty) return true;
            return s1 == s2;
        }

        public static void TryParseInt(string sVal, ref int iVal)
        {
            try
            {
                iVal = Int32.Parse(sVal);
            }
            catch (FormatException ){}
        }

        public static string UrlWithoutQuery(String url)
        {
            int ix = url.IndexOf("?");
            if (ix != -1) return url.Substring(0, ix);
            return url;
        }

        /// <summary>
        /// Fetches primary category. First in list if primaryCategoryPrefix not set, else
        /// the first in the list with matching prefix
        /// </summary>
        /// <param name="categories">Semicolon-separated list of strings</param>
        /// <param name="primaryCategoryPrefix">Optional character prefix</param>
        public static string GetPrimaryCategory(string categories, char? primaryCategoryPrefix)
        {
            if (categories == null) return null;
            var catList = categories.Split(';', ',');
            if (!primaryCategoryPrefix.HasValue) return catList[0].Trim();
            foreach (var cat in catList)
            {
                if (cat.Trim()[0] == primaryCategoryPrefix.Value) return cat.Trim();
            }
            return catList[0].Trim();
        }

        /// <summary>
        /// Returns the singleListName if in comma separated string categories, else first cat
        /// </summary>
        /// <param name="categories"></param>
        /// <param name="SingleListName"></param>
        /// <returns></returns>
        public static string GetSingleCategory(string categories, string SingleListName)
        {
            if (categories == null) return null;
            var catList = categories.Split(';', ',');
            foreach (var cat in catList)
            {
                if (cat.Trim() == SingleListName) return cat.Trim();
            }
            return catList[0].Trim();
        }
    }
}
